import tkinter as tk
from tkinter import ttk, messagebox
from file_size_scanner import scan_directory, FileInfo
import threading
import queue
import os

class SizeScannerApp:
    def __init__(self, master):
        self.master = master
        self.master.title("磁盘空间分析工具")
        self.master.geometry('800x600')
        
        # 顶部控制区域
        self.top_frame = ttk.Frame(master, padding="10 10 10 10")
        self.top_frame.grid(row=0, column=0, sticky=(tk.W, tk.E))
        
        self.path_label = ttk.Label(self.top_frame, text="扫描路径:")
        self.path_label.grid(row=0, column=0, sticky=tk.W)
        
        self.path_entry = ttk.Entry(self.top_frame, width=40)
        self.path_entry.grid(row=0, column=1, padx=5)
        self.path_entry.bind('<Return>', lambda event: self.start_scan())
        self.path_entry.bind('<FocusIn>', lambda event: self.path_entry.selection_range(0, tk.END))
        
        self.scan_btn = ttk.Button(self.top_frame, text="开始扫描", command=self.start_scan)
        self.scan_btn.grid(row=0, column=2, padx=5)
        
        self.up_btn = ttk.Button(self.top_frame, text="上级目录", command=self.navigate_up)
        self.up_btn.grid(row=0, column=3, padx=5)

        # 剪贴板扫描按钮
        self.clipboard_btn = ttk.Button(self.top_frame, text="", command=lambda: self.start_scan(use_clipboard=True))
        self.clipboard_btn.grid(row=0, column=4, padx=5)
        self._check_clipboard()
        
        # 初始化配置
        self.config = self.load_config()
        
        # 结果表格区域
        self.tree_frame = ttk.PanedWindow(master, orient=tk.HORIZONTAL)
        self.tree_frame.grid(row=1, column=0, sticky=tk.NSEW, pady=5)
        
        # 创建可调整的表格面板
        table_pane = ttk.Frame(self.tree_frame)
        self.tree_frame.add(table_pane, weight=1)
        
        self.tree = ttk.Treeview(table_pane, columns=('type', 'name', 'size', 'path'), show='headings')
        self.tree.column('path', width=0, stretch=tk.NO)
        self.vsb = ttk.Scrollbar(table_pane, orient="vertical", command=self.tree.yview)
        
        self.tree.grid(row=0, column=0, sticky=(tk.W, tk.E, tk.N, tk.S))
        self.vsb.grid(row=0, column=1, sticky=(tk.N, tk.S))
        
        # 配置列自动扩展
        table_pane.columnconfigure(0, weight=1)
        table_pane.rowconfigure(0, weight=1)
        
        # 配置主窗口布局权重
        master.columnconfigure(0, weight=1)
        master.rowconfigure(1, weight=1)
        self.tree.heading('type', text='类型')
        self.tree.heading('name', text='名称')
        self.tree.heading('size', text='大小 (GB)')
        self.tree.heading('path', text='路径')
        self.tree.column('type', width=100, stretch=tk.NO)
        self.tree.column('name', width=200, stretch=tk.YES)
        self.tree.column('size', width=100, stretch=tk.NO)
        self.tree.column('path', width=0, stretch=tk.NO)
        
        # 绑定事件
        self.tree.bind('<Button-1>', self.on_single_click)
        self.tree.bind('<Double-1>', self.on_double_click)
        self.tree.bind('<B1-Motion>', self._on_column_drag)
        
        self.vsb = ttk.Scrollbar(self.tree_frame, orient="vertical", command=self.tree.yview)
        self.tree.configure(yscrollcommand=self.vsb.set)
        
        self.tree.grid(row=0, column=0, sticky=(tk.W, tk.E, tk.N, tk.S))
        self.vsb.grid(row=0, column=1, sticky=(tk.N, tk.S))
        
        # 底部状态栏
        self.status_var = tk.StringVar()
        self.status_bar = ttk.Label(master, textvariable=self.status_var, relief=tk.SUNKEN)
        self.status_bar.grid(row=2, column=0, sticky=(tk.W, tk.E))
        
        # 配置网格布局
        master.columnconfigure(0, weight=1)
        master.rowconfigure(1, weight=1)
        
        # 新增初始化属性
        self.scan_thread = None
        self.should_stop = threading.Event()
        self.result_queue = queue.Queue()
        
        # 注册扫描回调
        from file_size_scanner import register_hook_observer
        register_hook_observer(self.update_status)
        
        # 窗口关闭事件
        self.master.protocol('WM_DELETE_WINDOW', self.on_window_close)

    def load_config(self):
        import configparser
        config = configparser.ConfigParser()
        if os.path.exists('config.ini'):
            config.read('config.ini')
            self.path_entry.insert(0, config.get('DEFAULT', 'last_path', fallback=''))
        return config

    def save_config(self):
        import configparser
        config = configparser.ConfigParser()
        config['DEFAULT'] = {'last_path': self.path_entry.get()}
        with open('config.ini', 'w') as f:
            config.write(f)

    def on_window_close(self):
        self.save_config()
        self.master.destroy()

    def navigate_up(self):
        current_path = self.path_entry.get()
        parent_path = os.path.dirname(current_path)
        if os.path.exists(parent_path):
            self.path_entry.delete(0, tk.END)
            self.path_entry.insert(0, parent_path)

    def start_scan(self, use_clipboard=False):
        if use_clipboard:
            self.path_entry.delete(0, tk.END)
            self.path_entry.insert(0, self.master.clipboard_get())
        raw_path = self.path_entry.get()
        
        # 智能路径补全
        if len(raw_path) == 1 and raw_path.isalpha():
            raw_path = f"{raw_path}:\\"
            
        if not os.path.exists(raw_path):
            messagebox.showerror("错误", "无效路径")
            return
        
        # 禁用按钮防止重复扫描
        self.scan_btn.config(state='disabled')
        self.status_var.set('准备开始扫描...')
        
        # 清空旧数据
        self.tree.delete(*self.tree.get_children())
        
        # 创建扫描线程
        self.scan_thread = threading.Thread(
            target=self._scan_worker,
            args=(self.path_entry.get(),)
        )
        self.scan_thread.start()
        
        # 启动结果处理
        self.master.after(100, self._process_results)

    def _scan_worker(self, path):
        try:
            items = scan_directory(path)
            self.result_queue.put(('done', items))
        except Exception as e:
            self.result_queue.put(('error', str(e)))

    def _process_results(self):
        while not self.result_queue.empty():
            status, data = self.result_queue.get()
            if status == 'done':
                for item in data:
                    self.tree.insert('', 'end', values=('文件' if item.type == 'file' else '文件夹', item.name, item.size_gb, item.path))
                self.status_var.set(f'扫描完成，共找到 {len(data)} 个项目')
            elif status == 'error':
                messagebox.showerror("扫描错误", data)
            self.scan_btn.config(state='normal')
        self.master.after(100, self._process_results)

    def on_single_click(self, event):
        # 通过事件坐标获取当前点击项
        row_id = self.tree.identify_row(event.y)
        if not row_id:
            return
        item = self.tree.item(row_id)
        path = item['values'][3]
        # 立即更新剪贴板
        self.master.clipboard_clear()
        self.master.clipboard_append(path)
        # 清除选中状态避免残留
        self.tree.selection_remove(self.tree.selection())
        
    def on_double_click(self, event):
        if not self.tree.selection():
            return
        item = self.tree.item(self.tree.selection()[0])
        path = item['values'][3]
        if os.path.exists(path):
            if item['values'][1] == 'file':
                os.startfile(path, 'open')
            else:
                os.startfile(path)
    
    def _on_column_drag(self, event):
        region = self.tree.identify_region(event.x, event.y)
        if region == "separator":
            self.tree.column(self.tree.identify_column(event.x), width=event.x)
            
    def _check_clipboard(self):
        try:
            path = self.master.clipboard_get().strip()
            if os.path.exists(path):
                self.clipboard_btn.config(text=f"扫描[{os.path.basename(path)}]")
                self.clipboard_btn.grid()
            else:
                self.clipboard_btn.grid_remove()
        except tk.TclError:
            self.clipboard_btn.grid_remove()
        self.master.after(1000, self._check_clipboard)

    def update_status(self, file_path):
        self.status_var.set(f'正在扫描: {file_path}')
        self.master.update_idletasks()

if __name__ == '__main__':
    root = tk.Tk()
    app = SizeScannerApp(root)
    root.mainloop()